﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IrisGenerator.Common.Core;
using IrisGenerator.Framework.RuleEngine;
using IrisGenerator.Framework.Messaging;
using IrisGenerator.Framework.Events;


namespace IrisGenerator.Common.DataTypes.Rules
{

    public class MetatypeRule:RuleBase<Metatype>,IDbBindableObjectRules
    {

        #region ctor

        public MetatypeRule(Metatype metatype)
            : base(metatype)
        {
            //_innerMetatype.Inserted += new EventHandler<BaseEventArgs<Metatype>>(_innerMetatype_Inserted);
            this.LinkedObject.Deleting += new EventHandler<BaseEventArgs<Metatype>>(_innerMetatype_Deleting);
        }

        #endregion

        #region Properties' Rules

        private bool MetIdIsValid(ref RuleErrorCollection returnValue)
        {
            bool result = true;

            //Rule 1: The Target Id has to have a value to be validated.
            if (this.LinkedObject.MetId == null || !this.LinkedObject.MetId.HasValue)
            {
                if (returnValue == null)
                    returnValue = new RuleErrorCollection();
                returnValue.Add(new RuleError("Metatype ID", RuleErrorType.PropertyRule, "An Identifier is mandatory"));
                result = false;
            }

            return result;
        }

        private bool MetCodeIsValid(ref RuleErrorCollection returnValue)
        {
            bool result = true;

            if (string.IsNullOrEmpty(this.LinkedObject.MetCode))
            {
                if (returnValue == null)
                    returnValue = new RuleErrorCollection();

                returnValue.Add(new RuleError("Metatype Code", RuleErrorType.PropertyRule, "Code is mandatory"));
                result = false;
            }

            return result;
        }

        private bool MetDescriptionIsValid(ref RuleErrorCollection returnValue)
        {
            return true;
        }

        #endregion

        #region Persistancy Rules

        #region IDbBindableObjectRules

        public bool CanInsert(ref RuleErrorCollection returnValue)
        {
            bool result = true;
            result = result & !MetIdIsValid(ref returnValue);
            result = result & MetCodeIsValid(ref returnValue);
            result = result & MetDescriptionIsValid(ref returnValue);

            if (PrimaryKeyExists())
            {
                if (returnValue == null)
                    returnValue = new RuleErrorCollection();

                returnValue.Add(new RuleError("Metatype Object Conflict", RuleErrorType.BusinessRule, "The id already exists"));
                result = false;
            }

            return (result);
        }

        private bool PrimaryKeyExists()
        {
            var tmp = Metatype.Load(this.LinkedObject.MetId);
            return (tmp != null);
        }

        public bool CanUpdate(ref RuleErrorCollection returnValue)
        {
            bool result = true;

            result = result & MetIdIsValid(ref returnValue);
            result = result & MetCodeIsValid(ref returnValue);
            result = result & MetDescriptionIsValid(ref returnValue);

            return result;
        }
        public bool CanDelete(ref RuleErrorCollection returnValue)
        {
            return MetIdIsValid(ref returnValue);
        }

        #endregion

        #region Events Handling

        private void _innerMetatype_Deleting(object sender, BaseEventArgs<Metatype> e)
        {
            if (e.FireMessage)
            {
                Message message = new Message("Are you sure you want to delete the metatype " + e.Argument.MetCode + "?"
                    + Environment.NewLine + "This action will delete all linked elements.", "Metatype deletion",
                    MessageButtons.YesNo, MessageIcon.Question, MessageDefaultButton.Button2);

                MessageResults result = OnMessageSend(new IrisGenerator.Framework.Messaging.MessageEventArgs<Metatype>(e.Argument, message));
                if (result != MessageResults.Yes)
                {
                    e.Cancel = true;
                    return;
                }
            }

            
            MetatypeEquivalences.Select_METATYPE_EQUIVALENCES_By_MET_ID(e.Argument.MetId).Delete();
            
        }

        /// <summary>
        /// Occures when a metatype is inserted. Adds the adequate rows to the 
        /// MetaType Equivalences.
        /// </summary>
        /// <param name="sender">The object that fires the event</param>
        /// <param name="e">The metatype base event args.</param>
        void _innerMetatype_Inserted(object sender, BaseEventArgs<Metatype> e)
        {
            AddMissingEquivalences(e.Argument);
        }

        #endregion

        #endregion

        #region Methods


        
        private void AddMissingEquivalences(Metatype metatype)
        {
            TargetCollection col = Target.GetAll();
            foreach (Target target in col)
            {
                MetatypeEquivalences equ = MetatypeEquivalences.Load(target.TarId, metatype.MetId);
                if (equ == null)
                {
                    equ = new MetatypeEquivalences();
                    equ.MetId = metatype.MetId;
                    equ.TarId = target.TarId;
                    equ.MetEquType = metatype.MetCode;
                    equ.Insert();
                }
            }
        }

        #endregion

    }

}
